#include "full_duplex_echo_server.h"
#include "../log.h"

void Session::Start()
{
    memset(m_read_buf.get(), 0, m_max_len);
    m_socket.async_read_some(boost::asio::buffer(m_read_buf.get(), m_max_len),
    [this, ptr = shared_from_this()](const boost::system::error_code& ec, size_t len){
        _HadnleRead(ec, len, ptr);
    });
}

void Session::Send(char* msg, size_t len)
{
    bool pending = false; // 发送队列是否为空 - false: 当前发送队列为空，可以发送数据
    
    std::unique_lock<std::mutex> lock(m_send_lock);
    if(!m_send_que.empty())
    {
        pending = true;
    }
    m_send_que.push(std::make_shared<MsgNode>(msg, len));

    if(pending) //发送队列不为空，不需要再次调用发送回调函数
    {
        return;
    }

    boost::asio::async_write(m_socket, boost::asio::buffer(msg, len),
        bind(&Session::_HandleWrite, this, std::placeholders::_1, shared_from_this()));
}


void Session::_HadnleRead(const boost::system::error_code& ec, size_t len, std::shared_ptr<Session> self_ptr)
{
    if(ec)
    {
        m_server->DeleteSession(m_uuid);
        log_error("Session::_HadnleRead error, code: {}, message: {}", ec.value(), ec.message());
        return;
    }

    log_info("server receive data: {}", m_read_buf.get());
    Send(m_read_buf.get(), len);
    memset(m_read_buf.get(), 0, m_max_len);
    m_socket.async_read_some(boost::asio::buffer(m_read_buf.get(), m_max_len),
        [this, ptr = shared_from_this()](const boost::system::error_code& ec, size_t len){
            _HadnleRead(ec, len, ptr);
        });
}

void Session::_HandleWrite(const boost::system::error_code& ec, std::shared_ptr<Session> self_ptr)
{
    if(ec)
    {
        m_server->DeleteSession(m_uuid);
        log_error("Session::_HandleWrite error, code: {}, message: {}", ec.value(), ec.message());
        return;
    }

    std::unique_lock<std::mutex> lock(m_send_lock);
    m_send_que.pop();
    if(m_send_que.empty())
    {
        return;
    }
    auto msg = m_send_que.front();

    boost::asio::async_write(m_socket, boost::asio::buffer(msg->m_data.get(), msg->m_max_len),
        bind(&Session::_HandleWrite, this, std::placeholders::_1, shared_from_this()));
}

//=============================================================================================================================

Server::Server(boost::asio::io_context&ioc, uint16_t port)
:m_ioc(ioc)
,m_acceptor(ioc, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port))
{
    _StartAccetp();
    log_debug("server start listening on port: {}", port);
}
void Server::DeleteSession(const std::string& uuid)
{
    std::unique_lock<std::mutex> lock(m_mutex);
    auto it = m_sessions.find(uuid);
    if(it == m_sessions.end())
    {
        return;
    }
    m_sessions.erase(it);
}

//使用智能指针解决程序崩溃问题
void Server::_StartAccetp()
{
    auto session = std::make_shared<Session>(m_ioc, this);
    m_acceptor.async_accept(session->GetSocket(), 
    [this, session](const boost::system::error_code& ec){
        _HandleAccept(session, ec);
    });
}
void Server::_HandleAccept(std::shared_ptr<Session> session, const boost::system::error_code& ec)
{
    if(ec)
    {
        log_error("Server::_HandleAccept error, code: {}, message: {}", ec.value(), ec.message());
        return;
    }

    {
        std::unique_lock<std::mutex> lock(m_mutex);
        m_sessions.insert(std::make_pair(session->GetUuid(), session));
    }
    session->Start();
    _StartAccetp();
}